use std::borrow::{Borrow, BorrowMut};
use std::cell::RefCell;
use std::sync::{Arc, Weak, RwLock, Mutex};

use crate::chess::player::Player;
use crate::chess::PieceColor;

#[derive(Debug, Clone)]
pub enum PointState {
    Kill,
    Piece(PieceColor)
}

#[derive(Debug)]
pub struct Point {
    id: u8,
    piece: Option<PointState>,
    v: Weak<Edge>,
    h: Weak<Edge>,
}

impl Point {
    pub fn new(id: u8) -> Point {
        Point{
            id,
            piece: None,
            h: Weak::new(),
            v: Weak::new(),
        }
    }

    pub fn init_edge(&mut self, h: Arc<Edge>, v: Arc<Edge>) {
        self.h.clone_from(&Arc::downgrade(&h));
        self.v.clone_from(&Arc::downgrade(&v));
        // self.h.write().unwrap() = AArc::downgrade(&h);
        // *self.h.borrow_mut() = AArc::downgrade(&h);
        // *self.v.borrow_mut() = AArc::downgrade(&v);
    }
}

#[derive(Debug)]
pub struct Edge {
    left: Arc<Point>,
    right: Arc<Point>,
    center: Arc<Point>,
}

impl Edge {
    pub fn new(left: Arc<Point>, center: Arc<Point>, right: Arc<Point>) -> Edge {
        Edge {
            left,
            right,
            center
        }
    }
}

pub enum ChessState {
    Put,
    Move,
    Kill,
    Over,
}

pub struct Chessboard {
    state: ChessState,
    points: Vec<Arc<Point>>,
    lines: Vec<Arc<Edge>>,
    current: Arc<Player>,
    opponent: Arc<Player>,
}

impl Chessboard {
    pub fn new() -> Chessboard {
        // let mut p00 = Arc::new(Point::new(0u8));
        // let mut p01 = Arc::new(Point::new(1u8));
        // let mut p02 = Arc::new(Point::new(2u8));
        // let mut p03 = Arc::new(Point::new(3u8));
        // let mut p04 = Arc::new(Point::new(4u8));
        // let mut p05 = Arc::new(Point::new(5u8));
        // let mut p06 = Arc::new(Point::new(6u8));
        // let mut p07 = Arc::new(Point::new(7u8));
        // let mut p08 = Arc::new(Point::new(8u8));
        // let mut p09 = Arc::new(Point::new(9u8));
        // let mut p10 = Arc::new(Point::new(10u8));
        // let mut p11 = Arc::new(Point::new(11u8));
        // let mut p12 = Arc::new(Point::new(12u8));
        // let mut p13 = Arc::new(Point::new(13u8));
        // let mut p14 = Arc::new(Point::new(14u8));
        // let mut p15 = Arc::new(Point::new(15u8));
        // let mut p16 = Arc::new(Point::new(16u8));
        // let mut p17 = Arc::new(Point::new(17u8));
        // let mut p18 = Arc::new(Point::new(18u8));
        // let mut p19 = Arc::new(Point::new(19u8));
        // let mut p20 = Arc::new(Point::new(20u8));
        // let mut p21 = Arc::new(Point::new(21u8));
        // let mut p22 = Arc::new(Point::new(22u8));
        // let mut p23 = Arc::new(Point::new(23u8));
        // let mut p24 = Arc::new(Point::new(24u8));

        let mut p00 = Point::new(0u8);
        let mut p01 = Point::new(1u8);
        let mut p02 = Point::new(2u8);
        let mut p03 = Point::new(3u8);
        let mut p04 = Point::new(4u8);
        let mut p05 = Point::new(5u8);
        let mut p06 = Point::new(6u8);
        let mut p07 = Point::new(7u8);
        let mut p08 = Point::new(8u8);
        let mut p09 = Point::new(9u8);
        let mut p10 = Point::new(10u8);
        let mut p11 = Point::new(11u8);
        let mut p12 = Point::new(12u8);
        let mut p13 = Point::new(13u8);
        let mut p14 = Point::new(14u8);
        let mut p15 = Point::new(15u8);
        let mut p16 = Point::new(16u8);
        let mut p17 = Point::new(17u8);
        let mut p18 = Point::new(18u8);
        let mut p19 = Point::new(19u8);
        let mut p20 = Point::new(20u8);
        let mut p21 = Point::new(21u8);
        let mut p22 = Point::new(22u8);
        let mut p23 = Point::new(23u8);
        let mut p24 = Point::new(24u8);

        let mut ap00 = Arc::new(p00);
        let mut ap01 = Arc::new(p01);
        let mut ap02 = Arc::new(p02);
        let mut ap03 = Arc::new(p03);
        let mut ap04 = Arc::new(p04);
        let mut ap05 = Arc::new(p05);
        let mut ap06 = Arc::new(p06);
        let mut ap07 = Arc::new(p07);
        let mut ap08 = Arc::new(p08);
        let mut ap09 = Arc::new(p09);
        let mut ap10 = Arc::new(p10);
        let mut ap11 = Arc::new(p11);
        let mut ap12 = Arc::new(p12);
        let mut ap13 = Arc::new(p13);
        let mut ap14 = Arc::new(p14);
        let mut ap15 = Arc::new(p15);
        let mut ap16 = Arc::new(p16);
        let mut ap17 = Arc::new(p17);
        let mut ap18 = Arc::new(p18);
        let mut ap19 = Arc::new(p19);
        let mut ap20 = Arc::new(p20);
        let mut ap21 = Arc::new(p21);
        let mut ap22 = Arc::new(p22);
        let mut ap23 = Arc::new(p23);
        let mut ap24 = Arc::new(p24);


        // let l01 = Arc::new(Edge::new(p00.clone(), p01.clone(), p02.clone()));
        // let l02 = Arc::new(Edge::new(p02.clone(), p03.clone(), p04.clone()));
        // let l03 = Arc::new(Edge::new(p04.clone(), p05.clone(), p06.clone()));
        // let l04 = Arc::new(Edge::new(p06.clone(), p07.clone(), p00.clone()));
        // let l05 = Arc::new(Edge::new(p08.clone(), p09.clone(), p10.clone()));
        // let l06 = Arc::new(Edge::new(p10.clone(), p11.clone(), p12.clone()));
        // let l07 = Arc::new(Edge::new(p12.clone(), p13.clone(), p14.clone()));
        // let l08 = Arc::new(Edge::new(p14.clone(), p15.clone(), p08.clone()));
        // let l09 = Arc::new(Edge::new(p16.clone(), p17.clone(), p18.clone()));
        // let l10 = Arc::new(Edge::new(p18.clone(), p19.clone(), p20.clone()));
        // let l11 = Arc::new(Edge::new(p20.clone(), p21.clone(), p22.clone()));
        // let l12 = Arc::new(Edge::new(p22.clone(), p23.clone(), p16.clone()));
        // let l13 = Arc::new(Edge::new(p01.clone(), p09.clone(), p17.clone()));
        // let l14 = Arc::new(Edge::new(p03.clone(), p11.clone(), p19.clone()));
        // let l15 = Arc::new(Edge::new(p05.clone(), p13.clone(), p21.clone()));
        // let l16 = Arc::new(Edge::new(p07.clone(), p15.clone(), p23.clone()));

        let l01 = Arc::new(Edge::new(ap00.clone(), ap01.clone(), ap02.clone()));
        let l02 = Arc::new(Edge::new(ap02.clone(), ap03.clone(), ap04.clone()));
        let l03 = Arc::new(Edge::new(ap04.clone(), ap05.clone(), ap06.clone()));
        let l04 = Arc::new(Edge::new(ap06.clone(), ap07.clone(), ap00.clone()));
        let l05 = Arc::new(Edge::new(ap08.clone(), ap09.clone(), ap10.clone()));
        let l06 = Arc::new(Edge::new(ap10.clone(), ap11.clone(), ap12.clone()));
        let l07 = Arc::new(Edge::new(ap12.clone(), ap13.clone(), ap14.clone()));
        let l08 = Arc::new(Edge::new(ap14.clone(), ap15.clone(), ap08.clone()));
        let l09 = Arc::new(Edge::new(ap16.clone(), ap17.clone(), ap18.clone()));
        let l10 = Arc::new(Edge::new(ap18.clone(), ap19.clone(), ap20.clone()));
        let l11 = Arc::new(Edge::new(ap20.clone(), ap21.clone(), ap22.clone()));
        let l12 = Arc::new(Edge::new(ap22.clone(), ap23.clone(), ap16.clone()));
        let l13 = Arc::new(Edge::new(ap01.clone(), ap09.clone(), ap17.clone()));
        let l14 = Arc::new(Edge::new(ap03.clone(), ap11.clone(), ap19.clone()));
        let l15 = Arc::new(Edge::new(ap05.clone(), ap13.clone(), ap21.clone()));
        let l16 = Arc::new(Edge::new(ap07.clone(), ap15.clone(), ap23.clone()));

        ap00.borrow_mut().init_edge(l01.clone(), l04.clone());

        // p00.init_edge(l01.clone(), l04.clone());
        // p01.init_edge(l01.clone(), l13.clone());
        // p02.init_edge(l01.clone(), l02.clone());
        // p03.init_edge(l02.clone(), l14.clone());
        // p04.init_edge(l02.clone(), l03.clone());
        // p05.init_edge(l03.clone(), l15.clone());
        // p06.init_edge(l03.clone(), l04.clone());
        // p07.init_edge(l04.clone(), l16.clone());
        // p08.init_edge(l05.clone(), l08.clone());
        // p09.init_edge(l05.clone(), l13.clone());
        // p10.init_edge(l06.clone(), l05.clone());
        // p11.init_edge(l06.clone(), l14.clone());
        // p12.init_edge(l07.clone(), l06.clone());
        // p13.init_edge(l07.clone(), l15.clone());
        // p14.init_edge(l08.clone(), l07.clone());
        // p15.init_edge(l08.clone(), l16.clone());
        // p16.init_edge(l09.clone(), l12.clone());
        // p17.init_edge(l09.clone(), l13.clone());
        // p18.init_edge(l10.clone(), l09.clone());
        // p19.init_edge(l10.clone(), l14.clone());
        // p20.init_edge(l11.clone(), l10.clone());
        // p21.init_edge(l11.clone(), l15.clone());
        // p22.init_edge(l12.clone(), l11.clone());
        // p23.init_edge(l12.clone(), l16.clone());

        Chessboard{
            state: ChessState::Put,
            points: vec![ap00.clone(),
                         ap01.clone(),
                         ap02.clone(),
                         ap03.clone(),
                         ap04.clone(),
                         ap05.clone(),
                         ap06.clone(),
                         ap07.clone(),
                         ap08.clone(),
                         ap09.clone(),
                         ap10.clone(),
                         ap11.clone(),
                         ap12.clone(),
                         ap13.clone(),
                         ap14.clone(),
                         ap15.clone(),
                         ap16.clone(),
                         ap17.clone(),
                         ap18.clone(),
                         ap19.clone(),
                         ap20.clone(),
                         ap21.clone(),
                         ap22.clone(),
                         ap23.clone(),
                         ap24.clone(),],
            lines: vec![l01.clone(),
                        l02.clone(),
                        l03.clone(),
                        l04.clone(),
                        l05.clone(),
                        l06.clone(),
                        l07.clone(),
                        l08.clone(),
                        l09.clone(),
                        l10.clone(),
                        l11.clone(),
                        l12.clone(),
                        l13.clone(),
                        l14.clone(),
                        l15.clone(),
                        l16.clone()],
            current: Arc::new(Player::new(PieceColor::Black)),
            opponent: Arc::new(Player::new(PieceColor::White)),
        }
    }
}